﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using Dapper;
using Aragorn.SOA.ORM.DapperExtensions;

namespace Aragorn.SOA.ORM
{
    public class SqlCommand
    {
        private string commandText;

        private DynamicParameters parameters;

        internal string CommandText
        {
            get
            {
                return this.commandText;
            }
        }

        private DbContextData Data
        {
            get;
            set;
        }

        public SqlCommand(DbContextData contextData, string sql)
        {
            this.Data = contextData;
            this.commandText = sql;
            this.parameters = new DynamicParameters();
        }

        public int Execute()
        {
            CommandType? nullable = null;
            return this.Data.Connection.Execute(this.commandText, this.Data, this.parameters, this.Data.Transaction, this.Data.CommandTimeout, nullable);
        }

        internal T Get<T>(object id)
        where T : class
        {
            return this.Data.Connection.Get<T>(id, this.Data, this.Data.Transaction, this.Data.CommandTimeout);
        }

        public SqlCommand Parameter(dynamic param)
        {
            this.parameters.AddDynamicParams(param);
            return this;
        }

        public SqlCommand Parameter(string name, object value, DbType? dbType = null, ParameterDirection? direction = null, int? size = null)
        {
            this.parameters.Add(name, value, dbType, direction, size);
            return this;
        }

        public IEnumerable<dynamic> QueryDynamicMany()
        {
            return this.QueryMany<object>();
        }

        public dynamic QueryDynamicSingle()
        {
            return this.QuerySingle<object>();
        }

        public IEnumerable<T> QueryMany<T>()
        {
            CommandType? nullable = null;
            return this.Data.Connection.Query<T>(this.commandText, this.Data, this.parameters, this.Data.Transaction, true, this.Data.CommandTimeout, nullable);
        }

        public IEnumerable<T> QueryPage<T>(int pageIndex, int pageSize, out int recordCount)
        {
            string countSql = DapperExtensions.DapperExtensions.SqlDialect.GetCountSql(this.commandText);
            recordCount = this.Data.Connection.ExecuteScalar<int>(countSql, this.Data, this.parameters, this.Data.Transaction, this.Data.CommandTimeout, null);
            IDictionary<string, object> dictionary = new Dictionary<string, object>();
            string pagingSql = DapperExtensions.DapperExtensions.SqlDialect.GetPagingSql(this.commandText, pageIndex, pageSize, dictionary);
            foreach (KeyValuePair<string, object> current in dictionary)
            {
                string text = current.Key;
                if (text.StartsWith("@"))
                {
                    text = text.Substring(1);
                }
                this.Parameter(text, current.Value, null, null, null);
            }
            return this.Data.Connection.Query<T>(pagingSql, this.Data, this.parameters, this.Data.Transaction, true, this.Data.CommandTimeout, null);
        }

        public T QuerySingle<T>()
        {
            IEnumerable<T> enumerable = this.QueryMany<T>();
            if (enumerable != null && enumerable.Count<T>() > 0)
            {
                return enumerable.FirstOrDefault<T>();
            }
            return default(T);
        }
    }
}
